package middle_man;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;

import config.Config;

public class ClientsAccepter extends Thread{
	private ServerSocket serverSocket;
	private int currentClientID;
	private SmartQueue sq;
	private boolean _terminate = false;
	private ArrayList<ClientHandler> clientsHandlers = new ArrayList<ClientHandler>();
	
	public ClientsAccepter(SmartQueue _sq) {
		currentClientID = 1;
		sq = _sq;
		try {
			serverSocket = new ServerSocket(Config.middle_man_port);
		} catch (IOException e) {
			System.err.println("Could not listen on port "+Config.middle_man_port);
			e.printStackTrace();
		}
	}
	
	public void terminate() {
		_terminate = true;
	}
	
	public ServerSocket getServerSocket() {
		return serverSocket;
	}
	
	public void run() {
		this.setName("MiddleMan - ClientsAccepter");
		try {
			System.err.println("Clients: Accepter running ...");
			while(!_terminate) {
				Socket clientSocket = null;
				try {
					clientSocket = serverSocket.accept();
				} catch(IOException e) {
					System.err.println("Clients Accepter: Accepting new client accept failed: " + e.getMessage());
				}
				
				if(clientSocket != null) {
					System.err.println("Clients Accepter: New client accepted: " + currentClientID);
					LinkedBlockingQueue<Request> q = sq.getRoundRobinQueue();
					//LinkedBlockingQueue<Request> q = sq.getRandomQueue();
					ClientHandler ch = new ClientHandler(q, currentClientID++, clientSocket);
					clientsHandlers.add(ch);
					ch.start();
				}
			}
			
			// So we have terminated, join all other clients
			for(ClientHandler ch : clientsHandlers) {
				try {
					ch.getClientSocket().close();
					synchronized(ch) {
						ch.shouldSleep = false;
						ch.notify();
					}
					ch.join();
				} catch(InterruptedException e) {
					// Really mean code in the try block, so no need to cover exceptions
				} catch(IOException e) {
					// Really mean code in the try block, so no need to cover exceptions
				}
			}
		} finally {
			System.err.println("Clients Accepter shut down.");
		}
	}
}
